package it.unibo.refolding.pico;

import it.unibo.refolding.common.CommonThings;
import it.unimi.dsi.fastutil.shorts.ShortArrayList;
import it.unimi.dsi.fastutil.shorts.ShortList;

import java.awt.Shape;
import java.awt.geom.Path2D;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;

public class DirectionData {

	protected final short[] deflection;
	protected final short[] z;

	DirectionData(short[] deflection, short[] z) {
		Preconditions.checkArgument(deflection.length == z.length);
		this.deflection = deflection;
		this.z = z;
	}
	
	public DirectionData subRange(int from, int to) {
		return new DirectionData(
			Arrays.copyOfRange(deflection, from, to), Arrays.copyOfRange(z, from, to));
	}
	
	public List<Shape> drawZ() {
		return draw(ShortArrayList.wrap(z));
	}
	
	public static List<Shape> draw(ShortList z) {
    Path2D.Float path = new Path2D.Float();
    if (!z.isEmpty()) {
      path.moveTo(0, z.getShort(0));
      for (int i = 1; i < z.size(); ++i) {
        path.lineTo(i, z.getShort(i));
      }
    }
    return ImmutableList.<Shape>of(path);
	}

	public int timeInstantCount() {
		return deflection.length;
	}

	public short[] sharedDeflectionArray() {
		return deflection;
	}

  public ShortList sharedDeflectionList() {
    return ShortArrayList.wrap(deflection);
  }

	public short[] copyOfDeflectionArray() {
		return Arrays.copyOf(deflection, deflection.length);
	}

	public short[] copyOfZArray() {
		return Arrays.copyOf(z, z.length);
	}

	public int actualZRange() {
		// negative!!!
		return z[z.length - 1] - z[0];
	}

	public short z(int i) {
		return z[i];
	}

	public short deflectionAtIndex(int index) {
		return deflection[index];
	}

	public short[] sharedZArray() {
		return z;
	}

  public ShortList sharedZList() {
    return ShortArrayList.wrap(z);
  }

	@Override
	public String toString() {
		return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}
	
	public short[] minMaxDeflection() {
		return new short[] {CommonThings.min(deflection), CommonThings.max(deflection)};
	}
	
	@Override
	public boolean equals(Object other) {
		if (other == null || getClass() != other.getClass()) {
			return false;
		}
		DirectionData o = (DirectionData) other;
		return Arrays.equals(deflection, o.deflection) && Arrays.equals(z, o.z);
	}
}
